home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-12-31 | 80.2 KB | 1,640 lines |
- /****************** "IMSHOW.C" Source Code File *************************/
- /* */
- /* PROGRAM-NAME: IMSHOW */
- /* ------------- */
- /* */
- /* */
- /* DEVELOPED BY: */
- /* ------------- */
- /* Martin Erzberger, 1989/93 */
- /* */
- /* */
- /* PURPOSE OF THE APPLICATION: */
- /* --------------------------- */
- /* - Display of pictures in the formats: */
- /* im ("a general purpose image file format") */
- /* bmp (OS/2 and Windows 3 Bitmaps) */
- /* GIF (Graphics Interchange Format) */
- /* */
- /* */
- /* VERSION: 2.02, 1/93 */
- /* -------- */
- /* */
- /* */
- /* PROGRAM HISTORY: */
- /* ---------------- */
- /* - 1.00, 12/89: First edition. */
- /* - 1.10, 1/90: Added conversion routines, */
- /* Supports new im library (0.93 beta), e.g. */
- /* - Better error management, */
- /* - Can read compressed pictures, */
- /* - More efficient storage of IMMAP pictures, */
- /* Userinterface now in english, */
- /* Userinterface now SAA compliant. */
- /* - 1.20, 7/91: 'Realize' function of OS/2 1.2 supported, */
- /* Can use long filenames, */
- /* Can now also read Windows 3 bitmaps, */
- /* Better error management in the conversion routines, */
- /* BMP2IM recognizes greyscale pictures. */
- /* - 2.00, 11/92: Version for OS/2 2.0, */
- /* im library now statically linked (it isn't reentrant */
- /* anyway), */
- /* Clipboard support gone, */
- /* Supports the palette manager instead of OS/2 1.2's */
- /* "realize" function, */
- /* Can now also read GIF pictures, */
- /* - 2.01, 11/92: Some bug fixes: */
- /* 'ESC=Cancel' didn't work with GIF's, */
- /* Better work around for 100% pictures, */
- /* GIF loader a bit faster. */
- /* - 2.02, 1/93: Bug fix: Now works also on TSENG video cards, */
- /* '100% work around' isn't necessary anymore, */
- /* Comments translated to english. */
- /* */
- /* */
- /* SOURCEFILES: */
- /* ------------ */
- /* */
- /* */
- /* IMSHOW.MAK - For NMAKE utility */
- /* IMSHOW.DEP - For NMAKE utility (both generated by Workframe/2) */
- /* IMSHOW.C - Main source code */
- /* IMSHOW.H - Header file */
- /* IMSHOW.ICO - Icon */
- /* IMSHOW.RC - Ressources (menus, strings) */
- /* BMLIB.C - Procedures for bitmap handling */
- /* BMLIB.H - Header */
- /* GIFLIB.C - Procedures for GIF file handling */
- /* GIFLIB.C - Header */
- /* FILEDLG.C - Procedures für the "File Open" dialog */
- /* IM.H - Header for the im library */
- /* */
- /* */
- /* */
- /* USED LIBRARIES: */
- /* --------------- */
- /* */
- /* IMLIB.LIB - im library */
- /* */
- /* USED SOFTWARE: */
- /* -------------- */
- /* */
- /* 'im' Library */
- /* IBM Operating System/2, Version 2.0 */
- /* IBM C Set/2 Compiler */
- /* IBM Toolkit for OS/2 2.0 */
- /* */
- /* USED LITERATURE: */
- /* ---------------- */
- /* IBM Operating System/2 1.2 Programming Tools and Information */
- /* IBM Corporation, 1988, */
- /* */
- /* Kerninghan, Brian W., Ritchie, Dennis M.: */
- /* "The C Programming Language", Second Edition, */
- /* Prentice Hall, 1988, 1978, ISBN: 0-13-110362-8 */
- /* */
- /* Petzold Charles: "Programming the OS/2 Presentation Manager", */
- /* Microsoft Press, 1989, ISBN: 1-55615-170-5 */
- /* */
- /* Schildt Herbert: "OS/2 Programming: An Introduction", */
- /* McGraw-Hill, 1988, ISBN: 0-07-881427-8 */
- /* */
- /* */
- /***************************************************************************/
- #define INCL_WIN /* Window manager headerfiles */
- #define INCL_GPILOGCOLORTABLE /* To use the palette manager */
- #define INCL_GPIBITMAPS /* Header for bitmaps */
- #define INCL_GPIPRIMITIVES /* Box, Line etc. */
- #define INCL_GPICONTROL /* For GpiResetPS */
- #define INCL_BITMAPFILEFORMAT /* Header for bitmapfiles */
- #define INCL_ERRORS /* Error definitions */
- #define INCL_DOSSEMAPHORES /* Header for semaphore handling */
-
- #include <os2.h> /* Main header file */
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
-
- #include "imshow.h" /* General identifiers */
- #include "bmlib.h" /* Bitmap subroutines */
- #include "giflib.h" /* GIF subroutines */
- #include "im.h" /* 'im' library header */
-
- /*#define DEBUG_NOPALETTE*/ /* To test a no palette manager system */
-
-
- /***************************************************************************/
- /* Variables to control Presentation Manager. */
- /***************************************************************************/
-
- HAB hab; /* PM anchor block handler */
- HMQ hmq; /* Message queue handler */
- HWND hwndClient; /* Client area window handler */
- HWND hwndFrame; /* Frame window handler */
- HWND hwndHscroll, hwndVscroll; /* Scrollbar handlers */
- HWND hwndDlg; /* Dialogbox handler */
- HPOINTER hptrArrow; /* Arrow mousepointer */
- HPOINTER hptrWait; /* Clock mousepointer */
- HDC hdc = NULLHANDLE; /* Screen devicecontext handler */
- HDC hdcMem = NULLHANDLE; /* Memory devicecontext handler */
- HPS hps = NULLHANDLE; /* Presentationspace handler */
- HPS hpsMem = NULLHANDLE; /* Memory pres. space handler */
- HBITMAP hbm = NULLHANDLE; /* Bitmap handler */
- PLONG plColTable; /* Pointer to colormap */
- PBITMAPINFO2 pbmiBitmap; /* Pointer to bitmapinfo */
- HPAL hpal = NULLHANDLE; /* Palette handler */
- ULONG flCreate = FCF_TITLEBAR | /* Window control flags */
- FCF_SYSMENU |
- FCF_MENU |
- FCF_MINMAX |
- FCF_SIZEBORDER |
- FCF_ACCELTABLE |
- FCF_ICON |
- FCF_TASKLIST |
- FCF_SHELLPOSITION |
- FCF_VERTSCROLL |
- FCF_HORZSCROLL;
- CHAR titleBar[80] = "imShow 2.02"; /* Titlebar text */
-
-
- /***************************************************************************/
- /* Other control variables. */
- /***************************************************************************/
-
- BOOL fCmdLine = FALSE; /* Command line argument there? */
- BOOL fFill = TRUE; /* Background must be erased? */
- BOOL bRealizeSupported; /* Realizing supported? */
- BOOL fRealized = FALSE; /* Palette realized? */
- HEV semInputReady; /* Loading thread can start */
- HEV semPictureReady; /* Picture is ready to display */
- HEV semHalt; /* Loading should stop */
- TID tidLoad; /* Thread-id of the loading thread */
- USHORT usMenuChecked = IDM_100; /* The checked menu */
- LONG lScaleFactor = 100; /* Scale factor of the picture */
- ULONG ulSemHelper; /* Dummy, used with semaphores */
-
-
- /***************************************************************************/
- /* Variables of the application */
- /***************************************************************************/
-
- USHORT usType; /* Picture type */
- USHORT usStorage; /* Storage method */
- USHORT usSamples; /* Samples per pixel */
- USHORT usDepth; /* Bitdepth per pixel */
- USHORT usColors; /* Number of picture colors */
- ULONG ulBytesPerLine; /* Bitmap bytes per line */
- CHAR szFileSource[80]; /* Picture filename */
- HFILE hImage; /* Handle to GIF and BMP file */
- PBYTE pbBitmapData = NULL; /* Buffer for imagedata */
- IMAGE *imBild; /* Handle to IM file */
- IMBYTE *imbRowBuff = NULL; /* Pointer to IM rowbuffer */
-
- ULONG ulDisplayColors; /* Number of screen colors */
-
- ULONG ulSizeX, ulSizeY; /* Size of the picture */
- LONG cxClient, cyClient; /* Size of the client area */
- LONG cxEdge, cyEdge; /* First visible picture dot */
- LONG cxScaled, cyScaled; /* Size of the scaled picture */
- LONG cxCut, cyCut; /* Size of visible part */
- BOOL fPicReadOK = FALSE; /* Picture was read in OK? */
-
-
- /***************************************************************************/
- /* Prototypes of functions. */
- /***************************************************************************/
-
- INT main (int argc, char *argv[]);
- MRESULT EXPENTRY WinProc (HWND, USHORT, MPARAM, MPARAM);
- VOID Init (HWND);
- VOID Paint (HWND);
- VOID SetScrollBars (LONG);
- BOOL MakePalette (PBITMAPINFO2, PLONG *);
- MRESULT EXPENTRY AboutDlgProc (HWND, USHORT, MPARAM, MPARAM);
- MRESULT EXPENTRY CancelDlgProc (HWND, USHORT, MPARAM, MPARAM);
- MRESULT EXPENTRY PropDlgProc (HWND, USHORT, MPARAM, MPARAM);
- VOID CentreDlgBox(HWND, HWND);
- VOID Help (HWND);
- BOOL OpenFile (HAB, HDC, HWND, HBITMAP *);
- VOID ReadFile (VOID* nichts);
- VOID ShowMsg (LONG, LONG, ULONG);
- VOID ImErrorMsg (int);
- USHORT GetFileType (CHAR *, HFILE *, IMAGE **);
-
- extern BOOL GetFileName (CHAR *, HWND, HWND, BOOL);
-
-
- /************************* Start of main() *******************************/
- /* */
- /* main() must do three things: */
- /* -Initialize PM (create the window, start threads etc.). */
- /* -Dispatch the messages to the correct window. */
- /* -Release the ressources and close the application. */
- /***************************************************************************/
-
- INT main(int argc, char *argv[])
- {
- QMSG qmsg; /* Message from message queue */
-
- /*************************************************************************/
- /* Initialize the application and PM: */
- /*************************************************************************/
- if (argc == 2) { /* Command line argument here? */
- strcpy (szFileSource, argv[1]); /* yup, copy it into szFileSource, */
- fCmdLine = TRUE; /* and set flag. */
- }
-
- hab = WinInitialize(0); /* Init PM */
-
- hmq = WinCreateMsgQueue(hab, 0); /* Create message queue */
-
- WinRegisterClass( /* Register window class */
- hab, /* Anchor block handle */
- "IMSHOWWindow", /* Classname */
- (PFNWP)WinProc, /* Address of window procedure */
- 0, /* No Flags */
- 0 /* No window words */
- );
-
- hwndFrame = WinCreateStdWindow( /* Create window */
- HWND_DESKTOP, /* Desktop is parent */
- WS_VISIBLE, /* Window is visible */
- (PULONG)&flCreate, /* Frame control flags */
- "IMSHOWWindow", /* Classname */
- "", /* Set title later */
- 0L, /* No window style */
- 0, /* Ressources in EXE file */
- ID_RESOURCE, /* Resource ID */
- (PHWND)&hwndClient /* client window handle */
- );
-
- DosCreateEventSem (0, &semInputReady, 0, 0); /* Init the semaphores */
- DosCreateEventSem (0, &semPictureReady, 0, 0);
- DosCreateEventSem (0, &semHalt, 0, 1);
-
- /* We will need this all the time, so let's allocate it here: */
- pbmiBitmap = malloc (sizeof(BITMAPINFOHEADER2) + 256*sizeof(RGB2));
-
- _beginthread (ReadFile, 0, 8192, 0); /* Start 2nd thread */
-
- /*************************************************************************/
- /* Dispatching of messages: */
- /*************************************************************************/
- while (WinGetMsg(hab, (PQMSG)&qmsg, (HWND)NULL, 0, 0))
- WinDispatchMsg(hab, (PQMSG)&qmsg);
-
- /*************************************************************************/
- /* Close application and release ressources: */
- /*************************************************************************/
- WinDestroyWindow(hwndFrame); /* Kill window */
- WinDestroyMsgQueue(hmq); /* Kill message queue */
- WinTerminate(hab); /* And end... */
- return (0);
- }
- /************************** End of main() ********************************/
-
-
-
- /******************** Start of the window procedure **********************/
- /* */
- /* The window procedure processes all messages from OS/2. */
- /* */
- /***************************************************************************/
-
- MRESULT EXPENTRY WinProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
- {
- ULONG ulTemp;
-
- switch(msg) /* In msg is the message */
- {
-
- case WM_CREATE: /* The window was just created */
- Init(hwnd); /* --> call Init() */
- break; /* and break to default msg handler */
-
- case WM_COMMAND: /* One of the menus was selected */
- switch (SHORT1FROMMP(mp1)) /* Which one is in mp1 */
- {
-
- case IDM_OPEN: /* "File, open" */
- OpenFile(hab, hdcMem, hwnd, &hbm); /* --> call function */
- break;
-
- case IDM_QUIT: /* Application should end */
- WinPostMsg(hwnd, WM_CLOSE, 0L, 0L);
- break;
-
- case IDM_ABOUT: /* About dialog box */
- WinDlgBox(HWND_DESKTOP, /* Desktop is parent (used for clipping)*/
- hwnd, /* hwnd gets the messages */
- (PFNWP)AboutDlgProc, /* Dialog procedure */
- 0, /* Template is in EXE file */
- IDD_ABOUT, /* ID of template */
- NULL); /* no more data */
- break;
-
- case IDM_FIT: /* All of the View xxx% */
- case IDM_25:
- case IDM_50:
- case IDM_75:
- case IDM_100:
- case IDM_200:
- case IDM_400:
- case IDM_800:
- if (SHORT1FROMMP(mp1) == usMenuChecked) /* Same as checked? */
- break;
- switch (SHORT1FROMMP(mp1)) { /* Set scale factor */
- case IDM_FIT:
- lScaleFactor = 0;
- break;
- case IDM_25:
- lScaleFactor = 25;
- break;
- case IDM_50:
- lScaleFactor = 50;
- break;
- case IDM_75:
- lScaleFactor = 75;
- break;
- case IDM_100:
- lScaleFactor = 100;
- break;
- case IDM_200:
- lScaleFactor = 200;
- break;
- case IDM_400:
- lScaleFactor = 400;
- break;
- case IDM_800:
- lScaleFactor = 800;
- break;
- }
- /* Move the check mark */
- WinCheckMenuItem (WinWindowFromID(hwndFrame, FID_MENU),
- SHORT1FROMMP(mp1), TRUE);
-
- WinCheckMenuItem (WinWindowFromID(hwndFrame, FID_MENU),
- usMenuChecked, FALSE);
-
- usMenuChecked = SHORT1FROMMP(mp1); /* Set for next time */
-
- SetScrollBars (lScaleFactor); /* Init. scrollbars */
-
- fFill = TRUE; /* Erase background */
- WinInvalidateRect( hwnd, NULL, FALSE); /* force redraw */
-
- break;
-
- case IDM_PROP: /* "Properties" dialog */
- WinDlgBox(HWND_DESKTOP, /* Desktop is parent (user for clipping)*/
- hwnd, /* hwnd gets messages */
- (PFNWP)PropDlgProc, /* Dialog procedure */
- 0, /* Template is in EXE file */
- IDD_PROP, /* ID of template */
- NULL); /* No more data */
- break;
-
- case IDM_HELPHELP: /* "Help, Help for Help" */
- Help(hwnd); /* call Help() */
- break;
-
- default: /* Default: break out to default */
- break; /* message processing */
-
- } /* End of "menu" switch */
- break;
-
-
- case WM_ERASEBACKGROUND: /* Background has to be erased */
- fFill = TRUE; /* Set appropriate flag */
- return (MRESULT)(FALSE); /* --> imShow will take care of it */
-
- case WM_PAINT: /* A repaint is necessary */
- Paint(hwnd); /* --> call Paint() */
- break;
-
- case WM_SIZE: /* The window was resized */
- cxClient = SHORT1FROMMP(mp2);
- cyClient = SHORT2FROMMP(mp2); /* Get new size */
- /* Is a picture ready? */
- if (DosWaitEventSem (semPictureReady, 0) != ERROR_TIMEOUT) {
- SetScrollBars (lScaleFactor); /* Yes, set scrollbars, */
- fFill = TRUE; /* erase background, */
- WinInvalidateRect( hwnd, NULL, FALSE); /* and force redraw */
- }
- break;
-
- case WM_REALIZEPALETTE: /* The palette has to be re-realized */
- if (!fRealized) /* If we don't have one currently: */
- break; /* --> break to default */
- else
- if (WinRealizePalette (hwndClient, hps, &ulTemp)) /* Realize it */
- WinInvalidateRect (hwnd, NULL, FALSE); /* and if necessary redraw*/
- return(0);
-
- case WM_VSCROLL: /* Message from vertical scrollbar */
- switch (SHORT2FROMMP (mp2)) { /* Message is in mp2 */
-
- case SB_LINEUP: /* Top arrow was clicked */
- cyEdge--; /* Scroll one pixel */
- break;
-
- case SB_PAGEUP: /* Click above slider */
- cyEdge -= cyCut; /* Scroll one screen full */
- break;
-
- case SB_PAGEDOWN: /* Click below slider */
- cyEdge += cyCut; /* Scroll one screen full */
- break;
-
- case SB_LINEDOWN: /* Bottom arrow was clicked */
- cyEdge++; /* Scroll one pixel */
- break;
-
- case SB_SLIDERPOSITION: /* Slider was dragged to the position */
- cyEdge = SHORT1FROMMP (mp2); /* given im mp2 */
- break;
-
- default: return 0; /* default: leave window procedure */
-
- } /* End of vertical scrollbat switch */
- /* The following part is reached by all case's above (except the */
- /* "default" part. */
-
- cyEdge = max (0, cyEdge); /* Reset position to a valid */
- cyEdge = min ((LONG)ulSizeY-cyCut, cyEdge); /* one */
-
- /* Set the slider to the new position: */
- WinSendMsg (hwndVscroll, SBM_SETPOS, MPFROMSHORT (cyEdge), NULL);
- /* And force a redraw: */
- WinInvalidateRect (hwnd, NULL, FALSE);
-
- break; /* Get out of WM_VSCROLL */
-
- case WM_HSCROLL: /* Message from horizontal scrollbar */
- switch (SHORT2FROMMP (mp2)) { /* The above comments apply also here*/
-
- case SB_LINELEFT: /* Left arrow */
- cxEdge--;
- break;
-
- case SB_PAGELEFT: /* Left from slider */
- cxEdge -= cxCut;
- break;
-
- case SB_PAGERIGHT: /* Right from slider */
- cxEdge += cxCut;
- break;
-
- case SB_LINERIGHT: /* Right arrow */
- cxEdge++;
- break;
-
- case SB_SLIDERPOSITION: /* New position */
- cxEdge = SHORT1FROMMP (mp2);
- break;
-
- default: return 0; /* Leave window procedure */
-
- } /* End of horizontal scrollbar switch */
-
- /* Again the common scrollbar part: */
-
- cxEdge = max (0, cxEdge);
- cxEdge = min ((LONG)ulSizeX-cxCut, cxEdge);
-
- WinSendMsg (hwndHscroll, SBM_SETPOS, MPFROMSHORT (cxEdge), NULL);
-
- WinInvalidateRect (hwnd, NULL, FALSE);
-
- break; /* Leave VM_HSCROLL */
-
- default: /* Default: Break to default window procedure */
- break;
-
- } /* End of window procedure switch */
-
- /* Most of the messages are now also passed to the default window */
- /* procedure. Of course, also all the not-processed messages get passed */
- /* (by the default: break statement above). */
-
- return WinDefWindowProc( hwnd, msg, mp1, mp2 );
- }
- /********************** End of the window procedure **********************/
-
-
-
- /************************** Start of Init() ******************************/
- /* */
- /* Initializations of the window. */
- /* */
- /* The initializations for the window must be done here, since only at */
- /* this place the window is already created, and one can ask e.g. the */
- /* size of it. */
- /* */
- /***************************************************************************/
-
- VOID Init(HWND hwnd) /* We only need hwnd from the WM_CREATE message. */
- {
- SIZEL sizlTemp;
- LONG plTempArray[1];
-
- DosResetEventSem (semPictureReady, &ulSemHelper); /* Picture not ready */
-
- /* We will need the scroll bars a lot, so we will get their ID's at this */
- /* place and put them in a global variable. Because hwndFrame isn't */
- /* known yet, the somewhat complicated methot with QW_PARENT is used. */
- hwndHscroll = WinWindowFromID
- (WinQueryWindow (hwnd, QW_PARENT), FID_HORZSCROLL);
- hwndVscroll = WinWindowFromID
- (WinQueryWindow (hwnd, QW_PARENT), FID_VERTSCROLL);
-
- /* We will also need the arrow and the clock pointer, so */
- /* we get their ID's also */
- hptrArrow = WinQuerySysPointer (HWND_DESKTOP, SPTR_ARROW, FALSE);
- hptrWait = WinQuerySysPointer (HWND_DESKTOP, SPTR_WAIT, FALSE);
-
- /* Now we set the titlebar text: */
- WinSetWindowText (WinQueryWindow (hwnd, QW_PARENT), titleBar);
-
- /* The following gets the size of a maximized window: */
- sizlTemp.cx = (LONG)((WinQuerySysValue (HWND_DESKTOP, SV_CXFULLSCREEN)-
- WinQuerySysValue (HWND_DESKTOP, SV_CXVSCROLL) + 1));
- sizlTemp.cy = (LONG)((WinQuerySysValue (HWND_DESKTOP, SV_CYFULLSCREEN)-
- WinQuerySysValue (HWND_DESKTOP, SV_CYMENU)-
- WinQuerySysValue (HWND_DESKTOP, SV_CYHSCROLL) + 1));
-
- /* Now we open a window device context to get some device capabilities: */
- hdc = WinOpenWindowDC (hwnd);
- if (hdc == (HDC)NULL) exit(1); /* Again, not very nice... */
-
- DevQueryCaps (hdc, CAPS_COLORS, 1L, plTempArray);
- ulDisplayColors = (ULONG)plTempArray[0]; /* Number of display colors */
-
- /* Is the palette manager supported? */
- DevQueryCaps (hdc, CAPS_ADDITIONAL_GRAPHICS, 1L, plTempArray);
- bRealizeSupported = (BOOL)((plTempArray[0] & CAPS_PALETTE_MANAGER));
-
- #ifdef DEBUG_NOPALETTE
- bRealizeSupported = FALSE;
- #endif
-
- /* Now we create a presentation space (we will keep this one until */
- /* the application ends). */
- hps = GpiCreatePS (hab, hdc, &sizlTemp,
- GPIA_ASSOC | PU_PELS | GPIF_DEFAULT);
- if (hps == (HPS)NULL) exit(1);
-
- /* Is there a file with the name specified on the command line? */
- if (fCmdLine) { /* Was there an argument? */
- if (fopen (szFileSource, "rb") == NULL) /* Try to open the file */
- fCmdLine = FALSE; /* Nope, --> clear flag */
- else {
- _fcloseall(); /* Yes: Close file again */
- /* and simulate a menu choice: */
- WinPostMsg (hwndFrame, WM_COMMAND, MPFROMSHORT(IDM_OPEN), NULL);
- } /* End if (fopen...) */
- } /* End if (FCmdLine) */
- } /* End Init() */
-
- /*************************** End of Init() *******************************/
-
-
-
- /************************** Start of Paint() *****************************/
- /* */
- /* Paint() processes the WM_PAINT messages of OS/2 PM. */
- /* */
- /* We always get a WM_PAINT message if parts of the client area become */
- /* invalid, e.g. by hiding and unhiding it by another window. */
- /* */
- /* One can force a WM_PAINT message by declaring the window as invalid */
- /* with the WinInvalidateRect call. */
- /* */
- /***************************************************************************/
-
- VOID Paint(HWND hwnd) /* We only need the window handler */
- /* mp1 and mp2 are NULL anyway... */
- {
- RECTL rc; /* Update region. */
- RECTL rcSource, rcDest; /* Source and target rectangles for bitmap */
-
-
- WinQueryUpdateRect (hwnd, &rc); /* Get the update region */
-
-
- /***************************************************************************/
- /* We don't need the semaphore below for synchronisation, we just want */
- /* to know if there is a picture ready to display. We get this information */
- /* by setting a timeout of 0, and then asking wether there was a timeout */
- /* or not. */
- /* If the semaphore was busy, then there is no picture ready yet, and we */
- /* simply draw the whole client area black. */
- /***************************************************************************/
- if (DosWaitEventSem (semPictureReady, 0L) == ERROR_TIMEOUT)
- WinFillRect (hps, &rc, CLR_BLACK);
-
- else { /* Ok, there is a picture */
- if (fFill) /* Do we have to reset the back- */
- /* ground first? */
- WinFillRect (hps, &rc, CLR_BLACK);/* Yes: Fill it black */
-
- fFill = FALSE; /* Reset flag */
-
- /* Next, we have to state which part of the bitmap we want to copy */
- /* in what rectangle: */
- rcDest.xLeft = 0; /* Dest., bottom left */
- rcDest.yBottom = 0; /* */
-
- if (cxCut > (LONG)ulSizeX) { /* Picture is slimmer than window: */
- rcDest.xRight = cxScaled; /* Destination, right */
- rcSource.xLeft = 0; /* Source, left */
- rcSource.xRight = (LONG)ulSizeX; /* Source, right */
- } else { /* Picture is broader than window: */
- rcDest.xRight = cxClient; /* Destination, right: */
- rcSource.xLeft = cxEdge; /* Source, left */
- rcSource.xRight = cxCut + cxEdge; /* Source, right */
- }
-
- if (cyCut > (LONG)ulSizeY) { /* Picture is less high than window */
- rcDest.yTop = cyScaled; /* Destination, top */
- rcSource.yBottom = 0; /* Source, bottom */
- rcSource.yTop = (LONG)ulSizeY; /* Source, top */
- } else { /* Picture is higher than window: */
- rcDest.yTop = cyClient; /* Destination, top */
- rcSource.yBottom = cyEdge; /* Source, bottom */
- rcSource.yTop = cyCut + cyEdge; /* Source, top */
- }
-
- /* The copy can take a while, so let's set the clock pointer: */
- WinSetPointer (HWND_DESKTOP, hptrWait);
-
- WinDrawBitmap(hps, /* Draw the bitmap... */
- hbm, /* From hbm to hps */
- &rcSource,
- (PPOINTL)&rcDest,
- 0,
- 1,
- DBM_NORMAL | DBM_STRETCH /* Stretch the bitmap */
- );
-
- WinSetPointer (HWND_DESKTOP, hptrArrow); /* Reset the pointer again.. */
-
- } /* End if */
-
- WinValidateRect (hwnd, &rc, FALSE); /* Window is now valid again. */
- }
- /*************************** End of Paint() ******************************/
-
-
-
- /*********************** Start of SetScrollBars() ************************/
- /* */
- /* SetScrollBars() initializes the scrollbars after a new file was loaded, */
- /* after a WM_SIZE message or when the scale rate was changed. */
- /* */
- /***************************************************************************/
-
- VOID SetScrollBars(LONG lScaleFactor)
- {
- cxEdge = 0; /* Reset the bottom left corner of the visible */
- cyEdge = 0; /* bitmap */
-
-
- if (ulSizeX == 0 || ulSizeY == 0) { /* Wrong picture?? */
- cxScaled = 0;
- cyScaled = 0;
- cxCut = 0;
- cyCut = 0;
- ulSizeX = 0;
- ulSizeY = 0;
- } else { /* Picture ok */
- if (lScaleFactor == 0) { /* i.e. "fit in window" */
- cyScaled = (LONG)ulSizeY * cxClient / (LONG)ulSizeX; /* Try to fit y */
- if (cyScaled > cyClient) { /* Too big? */
- cyScaled = cyClient; /* let y be, */
- cxScaled = (LONG)ulSizeX * cyClient / (LONG)ulSizeY; /* and fit x */
- } else /* fit y, */
- cxScaled = cxClient; /* and let x be */
- } else { /* other scale factor */
- cxScaled = (lScaleFactor * (LONG)ulSizeX) / 100; /* scale x, */
- cyScaled = (lScaleFactor * (LONG)ulSizeY) / 100; /* and y */
- } /* End if lScaleFactor == 0 */
-
- /* Now we have to calculate the amount of pixels that can be seen at */
- /* once. So if e.g. cxCut results to 30, 30 pixels of the source */
- /* bitmap data will fit in the x direction. One could also say, cxCut */
- /* is one "page" of the bitmap. If the window is 120 pixels */
- /* wide, the image is 240 pixels wide, and the scale factor is 200%, */
- /* then 30 pixels will fit. Easy, isn't it? */
- if (lScaleFactor == 0) { /* Again: option "fit in window" */
- cxCut = (LONG)ulSizeX * cxClient / cxScaled;
- cyCut = (LONG)ulSizeY * cyClient / cyScaled;
- } else { /* Other scale factor: */
- cxCut = (100 * cxClient) / lScaleFactor; /* Obvious */
- cyCut = (100 * cyClient) / lScaleFactor;
- } /* End if lScaleFactor == 0 */
- } /* End if Picture ok? */
-
-
- if (cxClient >= cxScaled) /* Window bigger than picture */
- WinEnableWindow (hwndHscroll, FALSE); /* -> Switch off scrollbar */
- else { /* Picture bigger than window */
- WinEnableWindow (hwndHscroll, TRUE); /* -> Switch on scrollbar */
-
- /* Now we set the endpoints of the scrollbar. The value range goes from */
- /* 0 to ulSizeX - cxCut. Why this? With 0, one can see the first cxCut */
- /* pixels, and with ulSizeX-cxCut, one can see the last cxCut pixels... */
- /* To go higher wouldn't make sense, one would have to put a blank bar */
- /* to the left of the picture. */
- WinSendMsg (hwndHscroll, SBM_SETSCROLLBAR, /* Set endpoints of scroll- */
- MPFROM2SHORT (0, 0), /* bar and put slider on */
- MPFROM2SHORT (0, (LONG)ulSizeX - cxCut)); /* position 0 */
- /* Then we set the slider size: It is set by giving the two values */
- /* "visible part" and "total part", which is cxCut and ulSizeX here. */
- WinSendMsg (hwndHscroll, SBM_SETTHUMBSIZE, /* Set the size of the */
- MPFROM2SHORT (cxCut, ulSizeX), /* slider */
- MPFROM2SHORT (0,0));
- } /* End if window bigger as picture */
-
- if (cyClient >= cyScaled) /* Same stuff for the */
- WinEnableWindow (hwndVscroll, FALSE); /* vertical scrollbar */
- else {
- WinEnableWindow (hwndVscroll, TRUE);
- WinSendMsg (hwndVscroll, SBM_SETSCROLLBAR,
- MPFROM2SHORT (0, 0),
- MPFROM2SHORT (0, (LONG)ulSizeY - cyCut));
- WinSendMsg (hwndVscroll, SBM_SETTHUMBSIZE,
- MPFROM2SHORT (cyCut, ulSizeY),
- MPFROM2SHORT (0,0));
- }
- }
-
- /************************* End of SetScrollBars() ************************/
-
-
-
- /************************ Start of MakePalette() *************************/
- /* */
- /* MakePalette creates the palette. */
- /* */
- /***************************************************************************/
-
- BOOL MakePalette (PBITMAPINFO2 pbmi, PLONG *plTable)
- {
- ULONG i, ulTemp;
-
- switch (pbmi->cBitCount) { /* Get the size of the table */
-
- case 8: /* 8 bits, --> 256 color entries */
- *plTable = malloc (256 * sizeof (LONG));
- break;
-
- case 4: /* 4 bits, --> 16 color entries */
- *plTable = malloc (16 * sizeof (LONG));
- break;
-
- default: /* other value shouldn't appear... */
- return FALSE;
- } /* Ende switch */
-
- if (*plTable == NULL)
- exit(1);
-
- for (i=0; i<usColors; i++) { /* Fill the table with the colors */
- (*plTable)[i] = (pbmi->argbColor[i].bRed * 65536L +
- pbmi->argbColor[i].bGreen * 256L +
- pbmi->argbColor[i].bBlue);
- }
- hpal = GpiCreatePalette (hab, 0, LCOLF_CONSECRGB, /* Create palette */
- (LONG)usColors, (PULONG)*plTable);
- free (plTable);
- GpiSelectPalette (hps, hpal); /* Select palette into hps */
- WinRealizePalette (hwndClient, hps, &ulTemp); /* and realize it */
- fRealized = TRUE; /* set flag */
- return TRUE;
- }
- /************************** End of MakePalette() *************************/
-
-
-
- /**************** Start of the About Box window procedure ****************/
- /* */
- /* Handles the messages to the "About" box. */
- /* */
- /***************************************************************************/
-
- MRESULT EXPENTRY AboutDlgProc(HWND hwndDlg, USHORT msg,
- MPARAM mp1, MPARAM mp2)
- {
- switch(msg)
- {
- case WM_INITDLG: /* On init, the box will be centered. */
- CentreDlgBox (hwndDlg, hwndClient);
- break;
-
- default: break;
- }
- return WinDefDlgProc(hwndDlg, msg, mp1, mp2);
- }
- /***************** End of the About Box window procedure *****************/
-
-
-
- /*************** Start of the Cancel Box window procedure ****************/
- /* */
- /* Processes the messages to the "Cancel" box. */
- /* */
- /* This dialog box appears while loading a picture, and gives the option */
- /* to cancel the loading procedure. */
- /* */
- /***************************************************************************/
-
- MRESULT EXPENTRY CancelDlgProc(HWND hwndDlg, USHORT msg,
- MPARAM mp1, MPARAM mp2)
- {
- switch(msg) {
-
- case WM_INITDLG:
- /* Set " % loaded" to 0: */
- WinSetDlgItemShort (hwndDlg, IDD_PERCENT, 0, FALSE);
- CentreDlgBox (hwndDlg, hwndClient); /* And center the dialog box */
- break;
-
- case WM_COMMAND:
- switch(COMMANDMSG(&msg)->cmd) {
- case DID_CANCEL: /* User wants to cancel the loading process */
- DosResetEventSem (semHalt, &ulSemHelper); /* --> inform the thread */
- return 0;
- }
- break;
-
- case WM_PROGRESS:
- /* The percent field must be updated */
- WinSetDlgItemShort (hwndDlg, IDD_PERCENT, SHORT1FROMMP(mp1), FALSE);
- break;
-
- case WM_FINISHED: /* The loading thread is finished */
- WinDismissDlg(hwndDlg, TRUE); /* --> End the dialog */
- return 0;
- }
- return WinDefDlgProc(hwndDlg, msg, mp1, mp2);
- }
- /**************** End of the Cancel Box window procedure *****************/
-
-
-
- /**************** Start of the Param Box window procedure ****************/
- /* */
- /* Processes the messages to the "Param" dialog box. */
- /* */
- /* The "Param" box displays the file properties. */
- /* */
- /***************************************************************************/
-
- MRESULT EXPENTRY PropDlgProc(HWND hwndDlg, USHORT msg,
- MPARAM mp1, MPARAM mp2)
-
- {
- switch(msg) {
- case WM_INITDLG:
- CentreDlgBox (hwndDlg, hwndClient); /* Centre box on init */
-
- switch (usStorage) { /* Set storage type */
- case IMRAW:
- WinSetDlgItemText (hwndDlg, IDD_STORAGE, "IMRAW");
- break;
-
- case IMRLE:
- WinSetDlgItemText (hwndDlg, IDD_STORAGE, "IMRLE");
- break;
-
- case IMLZW:
- WinSetDlgItemText (hwndDlg, IDD_STORAGE, "IMLZW");
- break;
-
- default:
- WinSetDlgItemText (hwndDlg, IDD_STORAGE, "?");
- }
-
- switch (usType) { /* Set file type */
- case OS2_101:
- WinSetDlgItemText (hwndDlg, IDD_TYPE, "OS/2, 1.1");
- WinSetDlgItemText (hwndDlg, IDD_STORAGE, "RAW");
- break;
-
- case WIN_3:
- WinSetDlgItemText (hwndDlg, IDD_TYPE, "WIN 3");
- WinSetDlgItemText (hwndDlg, IDD_STORAGE, "RAW");
- break;
-
- case GIF:
- WinSetDlgItemText (hwndDlg, IDD_TYPE, "GIF");
- WinSetDlgItemText (hwndDlg, IDD_STORAGE, "GIF");
- break;
-
- case OS2_200:
- WinSetDlgItemText (hwndDlg, IDD_TYPE, "OS/2, 2.0");
-
- switch (usStorage) {
- case BCA_UNCOMP:
- WinSetDlgItemText (hwndDlg, IDD_STORAGE, "RAW");
- break;
-
- case BCA_HUFFMAN1D:
- WinSetDlgItemText (hwndDlg, IDD_STORAGE, "HUFFM");
- break;
-
- case BCA_RLE4:
- WinSetDlgItemText (hwndDlg, IDD_STORAGE, "RLE4");
- break;
-
- case BCA_RLE8:
- WinSetDlgItemText (hwndDlg, IDD_STORAGE, "RLE8");
- break;
-
- case BCA_RLE24:
- WinSetDlgItemText (hwndDlg, IDD_STORAGE, "RLE24");
- break;
-
- default:
- WinSetDlgItemText (hwndDlg, IDD_STORAGE, "?");
- } /* endswitch */
- break;
-
- case IMGRY:
- WinSetDlgItemText (hwndDlg, IDD_TYPE, "IMGRY");
- break;
-
- case IMRGB:
- WinSetDlgItemText (hwndDlg, IDD_TYPE, "IMRGB");
- break;
-
- case IMMAP:
- WinSetDlgItemText (hwndDlg, IDD_TYPE, "IMMAP");
- break;
-
- case IMFLT:
- WinSetDlgItemText (hwndDlg, IDD_TYPE, "IMFLT");
- break;
-
- default:
- WinSetDlgItemText (hwndDlg, IDD_TYPE, "?");
- }
-
-
-
- WinSetDlgItemShort (hwndDlg, IDD_SIZEX, (USHORT)ulSizeX, FALSE);
- WinSetDlgItemShort (hwndDlg, IDD_SIZEY, (USHORT)ulSizeY, FALSE);
- WinSetDlgItemShort (hwndDlg, IDD_SAMPLES, usSamples, FALSE);
- WinSetDlgItemShort (hwndDlg, IDD_DEPTH, usDepth, FALSE);
- WinSetDlgItemShort (hwndDlg, IDD_COLORS, usColors, FALSE);
-
- break;
-
- default: break;
-
- }
- return WinDefDlgProc(hwndDlg, msg, mp1, mp2);
- }
- /***************** End of the Param Box window procedure *****************/
-
-
-
-
- /*********************** Start of CentreDlgBox() *************************/
- /* */
- /* CentreDlgBox places the given dialog box in the center of the */
- /* stated window. */
- /* */
- /***************************************************************************/
-
- VOID CentreDlgBox(HWND hwndDlg, HWND hwndParent)
- {
- LONG ix, iy; /* New position of the dialog box */
- LONG iwidth, idepth; /* Size of the display */
- SWP swp; /* Window informations */
- RECTL rect; /* Size of the window */
-
- /*************************************************************************/
- /* Get size of display */
- /*************************************************************************/
- iwidth = (SHORT)WinQuerySysValue (HWND_DESKTOP, SV_CXSCREEN );
- idepth = (SHORT)WinQuerySysValue (HWND_DESKTOP, SV_CYSCREEN );
-
- /*************************************************************************/
- /* Get size of window and norm it to screen */
- /*************************************************************************/
- WinQueryWindowRect (hwndParent, &rect);
- WinMapWindowPoints (hwndParent, HWND_DESKTOP, (PPOINTL)&rect, 2);
-
- /*************************************************************************/
- /* Get window informations of the dialog box */
- /*************************************************************************/
- WinQueryWindowPos (hwndDlg, (PSWP)&swp);
-
- /*************************************************************************/
- /* Calculate new position */
- /*************************************************************************/
- ix = ((rect.xRight - rect.xLeft - swp.cx) / 2) + rect.xLeft;
- iy = ((rect.yTop - rect.yBottom - swp.cy) / 2) + rect.yBottom;
-
- /*************************************************************************/
- /* Make shure, that the box is totally visible */
- /*************************************************************************/
- ix = max (ix, 0);
- ix = min (ix, (iwidth - swp.cx));
-
- iy = max (iy, 0);
- iy = min (iy, (idepth - swp.cy));
-
- /*************************************************************************/
- /* Set the new position */
- /*************************************************************************/
- WinSetWindowPos( hwndDlg, HWND_TOP, ix, iy, 0, 0, SWP_MOVE );
- }
- /************************ End of CentreDlgBox() **************************/
-
-
-
- /*************************** Start of Help() ****************************/
- /* */
- /* There is no online help in this application (well, there's no offline */
- /* help either...). */
- /* This function call merely gives this information. */
- /* */
- /***************************************************************************/
- VOID Help(HWND hwnd)
- {
- char title[20];
- char help[200];
-
- WinLoadString(hab, /* Get title of help box */
- 0,
- IDS_HELPTITLE,
- 20,
- title
- );
- WinLoadString(hab, /* Get content string of help box */
- 0,
- IDS_HELP,
- 200,
- help
- );
- WinMessageBox(HWND_DESKTOP, /* Display help box */
- hwnd,
- help,
- title,
- 0,
- MB_OK | MB_NOICON
- );
- /* Don't know how to remove the WC_SAVEBITS option, so the whole */
- /* window has to be invalidated (see also imShow.rc) */
- WinInvalidateRect( hwnd, NULL, FALSE);
- }
- /**************************** End of Help() ******************************/
-
-
-
- /************************** Begin of OpenFile() **************************/
- /* */
- /* OpenFile() will be called when the user selects "File, open" or when */
- /* there was a valid command line argument. */
- /* */
- /***************************************************************************/
-
- BOOL OpenFile(HAB hab, HDC hdcMem, HWND hwnd, HBITMAP *hbm)
- {
- ULONG ulTemp;
- ULONG ulIndex;
- LONG lReturn;
- IMBYTE *pimMap;
- SIZEL size; /* Size of presentation space */
-
-
- if (fCmdLine) fCmdLine = FALSE; /* Was there an argument on startup? */
- /* No: show file dialogbox: */
- else if (!GetFileName (szFileSource, HWND_DESKTOP, hwnd, TRUE))
- return 0;
-
- fFill = TRUE; /* Window has to be cleared afterwards */
-
- usType = GetFileType (szFileSource, &hImage, &imBild); /* Get type */
-
- /* The not used fields of pbmiBitmap MUST be 0, or OS/2 will choke */
- memset (pbmiBitmap, 0, sizeof (BITMAPINFOHEADER2)+256*sizeof(RGB2));
-
- switch (usType) {
- case BITMAP: /* File is a bitmap */
- bmrhdr (hImage, pbmiBitmap); /* Read in the header */
-
- ulSizeX = pbmiBitmap->cx; /* Copy some parameters into globals */
- ulSizeY = pbmiBitmap->cy;
-
- /* Now distinguish the type even further: */
- if (pbmiBitmap->cbFix == 12) /* Must be an OS/2 1.1 bitmap */
- usType = OS2_101;
- else if ((pbmiBitmap->cbFix < 41) && /* A Win 3 header is smaller */
- /* and doesn't support compressed bitmaps */
- (pbmiBitmap->ulCompression == BCA_UNCOMP))
- usType = WIN_3;
- else usType = OS2_200;
- /* We stuff all bitmaps into a full header, leaving the not needed */
- pbmiBitmap->cbFix = 64; /* fields with a value of 0 */
- usStorage = (USHORT)pbmiBitmap->ulCompression; /* Copy more parameters */
- usDepth = pbmiBitmap->cBitCount; /* as depth, */
- usSamples = pbmiBitmap->cPlanes; /* no. of planes, */
- usColors = (USHORT)(1 << usDepth); /* and no. of colors */
- break; /* finished with BMP's */
-
- case GIF: /* File is a GIF */
- if ((lReturn = gifrhdr (hImage, pbmiBitmap)) == 0) { /* Get header */
- ulSizeX = pbmiBitmap->cx; /* Copy some parameters into globals */
- ulSizeY = pbmiBitmap->cy;
- usStorage = 0; /* Not needed with GIF's */
- usColors = (USHORT)(1 << pbmiBitmap->cBitCount); /* Get no. of colors*/
- switch (pbmiBitmap->cBitCount) { /* OS/2 needs bitcount of 1, 4, or 8*/
- case 2:
- case 3:
- case 4:
- pbmiBitmap->cBitCount = 4;
- break;
- case 5:
- case 6:
- case 7:
- case 8:
- pbmiBitmap->cBitCount = 8;
- break;
- } /* endswitch */
- usDepth = pbmiBitmap->cBitCount;
- usSamples = pbmiBitmap->cPlanes;
- if (usDepth != 24) { /* Don't know if there are 24 bit GIF's?? */
- pbmiBitmap->cclrUsed = usColors; /* Palette manager can maybe make */
- pbmiBitmap->cclrImportant = usColors; /* use of this fields */
- }
- } else { /* If we couldn't read the GIF header, display an error msg. */
- ShowMsg (IDS_GIFERR, -lReturn, MB_ERROR);
- return 1;
- }
- break; /* Finished with GIF's */
-
- case IM: /* File is an IM */
- if (imrhdr (imBild)) { /* Get header */
- ImErrorMsg (imerrnum); /* If error, display message */
- return 0;
- }
- ulSizeX = imgetxsize(imBild); /* Get some properties of the picture */
- ulSizeY = imgetysize(imBild);
- usType = imgettype (imBild);
- if (usType == IMFLT) { /* IMFLT can't be displayed */
- ShowMsg (IDS_ERRTITLE, IDS_FLTERR, MB_ERROR);
- return 0;
- }
- usStorage = imgetstor (imBild); /* Get some more properties */
- usDepth = imgetdepth (imBild);
- usSamples = imgetsamples (imBild);
- if (usType == IMGRY) /* IMGRY gives wrong no. of colors */
- usColors = (USHORT)(1 << usDepth);
- else
- usColors = (USHORT)imgetcolors (imBild);
-
- /* Allocate row buffer */
- imbRowBuff = imrowalloc ((USHORT)ulSizeX, usSamples, usDepth);
- if (imbRowBuff == NULL) return 1;
-
- switch (usType) { /* Further processing different for the IM types */
- case IMRGB: /* IMRGB is a 24 bit, no colormapped, RGB picture */
- /* Allocate room for IM header */
- pbmiBitmap->cBitCount = 24;
- break;
-
- case IMGRY: /* IMGRY is a grayscale, with no explicit colormap */
- if (usDepth < 3) /* Set bitdepth to 1,2,4 or 8 */
- pbmiBitmap->cBitCount = usDepth;
- else if (usDepth < 5)
- pbmiBitmap->cBitCount = 4;
- else
- pbmiBitmap->cBitCount = 8;
- pbmiBitmap->cclrUsed = usColors;
- pbmiBitmap->cclrImportant = usColors;
- /*********************************************************************/
- /* OS/2 doesn't know about grayscales with no explicit colormap, */
- /* so we have to generate a gray colormap. */
- /*********************************************************************/
- ulTemp = (255 / ((1<<(ULONG)usDepth)-1)); /* Calculate increment */
- for (ulIndex = 0; ulIndex < (1<<(ULONG)usDepth); ulIndex++) {
- pbmiBitmap->argbColor[ulIndex].bBlue = (BYTE)(ulIndex * ulTemp);
- pbmiBitmap->argbColor[ulIndex].bGreen = (BYTE)(ulIndex * ulTemp);
- pbmiBitmap->argbColor[ulIndex].bRed = (BYTE)(ulIndex * ulTemp);
- } /* End for */
- break;
-
- case IMMAP:
- pimMap = (IMBYTE *)immapalloc (usColors); /* Allocate colormap */
- imsetcmap (imBild, (IMPIXEL *)pimMap); /* Set pointer to colormap */
- if (imrcmap (imBild)) { /* Get colormap */
- ImErrorMsg (imerrnum);
- return 0;
- }
-
- if (usColors > 257) { /* Too much colors... */
- pbmiBitmap->cBitCount = 24; /* So make an RGB picture */
-
- } else { /* No. colors ok */
- if (usColors > 16) /* 32 to 256 colors: 8 Bits */
- pbmiBitmap->cBitCount = 8; /* */
- else if (usColors > 4) /* 8 to 16 colors: 4 Bits */
- pbmiBitmap->cBitCount = 4; /* */
- else if (usColors > 2) /* 4 colors: 2 Bits */
- pbmiBitmap->cBitCount = 2;
- else
- pbmiBitmap->cBitCount = 1; /* 2 colors: 1 Bit */
- pbmiBitmap->cclrUsed = usColors;
- pbmiBitmap->cclrImportant = usColors;
- } /* End if too much colors */
-
- /* Copy colormap into header: */
- for (ulIndex = 0; ulIndex < usColors; ulIndex++) {
- pbmiBitmap->argbColor[ulIndex].bBlue = *(pimMap + 4*ulIndex + 2);
- pbmiBitmap->argbColor[ulIndex].bGreen = *(pimMap + 4*ulIndex + 1);
- pbmiBitmap->argbColor[ulIndex].bRed = *(pimMap + 4*ulIndex);
- } /* End for */
- free (pimMap); /* Release IM colormap */
- break;
- } /* End switch */
-
- pbmiBitmap->cbFix = 64; /* Again common for all IM types */
- pbmiBitmap->cx = ulSizeX;
- pbmiBitmap->cy = ulSizeY;
- pbmiBitmap->cPlanes = 1;
- break;
-
- case IMERROR: /* Type was an IM, but there was some sort of error */
- ImErrorMsg (imerrnum); /* Display this error */
- return 0;
-
- case UNKNOWN: /* Picture type is not supported */
- ShowMsg (IDS_ERRTITLE, IDS_TYPEERR, MB_ERROR);
- return 0;
-
- default: /* Shouldn't occur */
- return 0;
- } /* endswitch */
-
- /*************************************************************************/
- /* */
- /* Until now we got the bitmap header. Next we will load the image */
- /* data into a buffer. */
- /* */
- /*************************************************************************/
- strcat (szFileSource, " (imShow 2.02)");
- WinSetWindowText (hwndFrame, szFileSource); /* Set window title */
-
- /* We have to know this global variable: */
- ulBytesPerLine = ((pbmiBitmap->cBitCount * pbmiBitmap->cx + 31) / 32
- * pbmiBitmap->cPlanes * 4);
-
- pbBitmapData = malloc(ulBytesPerLine * pbmiBitmap->cy); /* Alloc Buffer */
- if (pbBitmapData == NULL) exit(1); /* No good error handling... */
-
- /************************************************************************/
- /* At this place was a very hard to find race condition: I cleared */
- /* the semaphore (which tells the loading thread to start) before I */
- /* created the dialog. On VERY small pictures, the thread was finished */
- /* before the dialog box was properly initialized. The message from the */
- /* thread to the dialog (telling it is finished) couldn't be delivered, */
- /* and there we had the Trap D... */
- /* Now it works. */
- /************************************************************************/
- hwndDlg = WinLoadDlg(HWND_DESKTOP, /* Load "cancel" dialog */
- hwnd,
- (PFNWP)CancelDlgProc,
- 0,
- IDD_CANCEL,
- NULL);
-
- DosResetEventSem (semPictureReady, &ulSemHelper); /* Picture not ready */
- DosPostEventSem (semInputReady); /* Loading thread can start */
-
- WinProcessDlg (hwndDlg); /* Process messages to dialog */
- WinDestroyWindow (hwndDlg); /* After finishing, clear it */
-
- if (fPicReadOK == TRUE) { /* The picture was read in successfully */
- /* Now we reset and allocate some ressources: */
- SetScrollBars(lScaleFactor); /* Initialize scrollbars */
-
- if (*hbm != (HBITMAP) NULL) { /* Is there a bitmap from before? */
- if (hpal != NULLHANDLE) { /* Did we have a palette? */
- GpiSelectPalette (hps, NULLHANDLE); /* Yes: Release it */
- GpiDeletePalette (hpal);
- hpal = NULLHANDLE;
- }
- GpiSetBitmap (hps, (HBITMAP)NULL); /* Release bitmap here.. */
- if (hpsMem != NULLHANDLE) {
- GpiSetBitmap (hpsMem, (HBITMAP)NULL); /* or maybe here, */
- GpiDeleteBitmap (*hbm); /* and delete it */
- GpiAssociate (hpsMem, (HDC)NULL); /* and old memory */
- GpiDestroyPS (hpsMem); /* presentation space */
- hpsMem = NULLHANDLE;
- DevCloseDC(hdcMem); /* Close memory dev. cont. */
- } else
- GpiDeleteBitmap (*hbm); /* Else delete only bitmap */
- }
-
- GpiResetPS (hps, GRES_ALL); /* Make shure the PS is "fresh" again */
-
- if (pbBitmapData == NULL) /* something wrong? */
- return (1);
-
- if (bRealizeSupported && /* Can we realize the palette? */
- ((USHORT)ulDisplayColors >= (1 << pbmiBitmap->cBitCount))) {
- MakePalette (pbmiBitmap, &plColTable); /* Make new palette */
- *hbm = GpiCreateBitmap(hps, /* Make new bitmap */
- (PBITMAPINFOHEADER2)pbmiBitmap,
- CBM_INIT, /* Initialize it with */
- (PBYTE)pbBitmapData, /* data in buffer */
- pbmiBitmap
- );
- GpiSetBitmap(hps, *hbm); /* Select bitmap in HPS */
- DosPostEventSem (semPictureReady); /* Picture is now ready */
- WinInvalidateRect (hwnd, NULL, FALSE); /* Force redraw */
-
- } else { /* We can't realize the palette */
- /* First create a memory device context: */
- hdcMem = DevOpenDC(hab, /* Anchor block handler */
- OD_MEMORY, /* Memory device context */
- (PSZ)"*", /* no device information */
- 0, /* no datablocks */
- NULL, /* no datablocks */
- NULLHANDLE /* compatible to screen-DC */
- );
- if (hdcMem == (HDC)NULL) /* Not a very nice error */
- exit(1); /* handling... */
-
- hpsMem = GpiCreatePS(hab, /* We need a memory PS */
- hdcMem, /* for hdcMem */
- (PSIZEL)&size,
- (LONG)PU_PELS | GPIT_NORMAL | GPIA_ASSOC | GPIF_DEFAULT
- );
- if (hpsMem == (HPS)NULL) exit(1); /* Some day I will improve this.. */
-
- *hbm = GpiCreateBitmap(hpsMem, /* Create bitmap */
- (PBITMAPINFOHEADER2)pbmiBitmap,
- 0L, /* Don't init it */
- (PBYTE)NULL,
- 0
- );
- if (*hbm == (HBITMAP)NULL) exit(1);
-
- GpiSetBitmap(hpsMem, *hbm); /* Select bitmap into PS */
-
- /* and now set the bitmap bits into the bitmap */
- /* This can take a while, so let's set the clock pointer: */
- WinSetPointer (HWND_DESKTOP, hptrWait);
- GpiSetBitmapBits (hpsMem, 0, (LONG)ulSizeY, pbBitmapData, pbmiBitmap);
- WinSetPointer (HWND_DESKTOP, hptrArrow); /* Reset the pointer.. */
-
- /* If we realized before, this will undo it: */
- WinRealizePalette (hwndClient, 0, &ulTemp);
- fRealized = FALSE;
-
- DosPostEventSem (semPictureReady); /* Picture is ready to display */
- WinInvalidateRect (hwnd, NULL, FALSE); /* Force redraw */
- } /* End if "can we realize" */
- free (pbBitmapData); /* Release Buffer */
-
- } else /* Picture was not read in successfully: */
- WinInvalidateRect (hwnd, NULL, FALSE); /* Clears client area */
-
- return 1;
- }
- /*************************** End of OpenFile() ***************************/
-
-
- /********************** Begin of the thread ReadFile *********************/
- /* */
- /* The thread ReadFile() reads in the picture data asynchronously. */
- /* It is implemented as an endless loop and is contolled via semaphores. */
- /* */
- /***************************************************************************/
- VOID ReadFile (VOID* nothing) /* We HAVE to to this for _beginthread.. */
- {
-
- PBYTE pbTemp; /* 2nd pointer to bitmapdata */
- register ULONG x,y; /* Loop variables */
- ULONG ulProgress; /* For the progress indicator */
- IMPIXEL impPixel; /* One IM pixel */
- ULONG ulChunk; /* Size of a data block */
-
- while (TRUE) { /* Start of endless loop */
- DosWaitEventSem (semInputReady, SEM_INDEFINITE_WAIT);/* Wait here... */
- DosResetEventSem (semInputReady, &ulSemHelper); /* Reset semaphore */
- fPicReadOK = FALSE; /* Picture (not yet) ok */
-
- switch (usType) { /* Read depending on type */
- case OS2_101: /* The bitmap DATA is equal on */
- case WIN_3: /* all types, only the header */
- case OS2_200: /* differs */
- bmrrows (hImage, pbBitmapData, 0, ulSizeY); /* Get all at once */
- WinPostMsg (hwndDlg, WM_PROGRESS, MPFROMSHORT(100), 0L); /* dummy */
- fPicReadOK = TRUE; /* read in ok */
- break; /* that's it... */
-
- case IMRGB: /* IM type IMRGB (24 bit) */
- /*******************************************************************/
- /* Unfortunately, the picture data of IM is different from OS/2... */
- /*******************************************************************/
- for (y=ulSizeY; y>0; y--) { /* OS/2 bitmaps stand on head... */
- /* Here we test the semaphore semHalt. It will be set when the */
- /* user chooses "ESC=Cancel" on the dialog. We don't want to */
- /* wait for the semaphore, we just want to see if it is set: */
- if (DosWaitEventSem (semHalt, 0L) == ERROR_TIMEOUT)
- goto Halt; /* Not very elegant, but by far the easiest way... */
- /* Read one row of image data: */
- if ((!imrrow (imBild, imbRowBuff) && imerrnum)) {
- ImErrorMsg (imerrnum);
- goto Halt;
- }
- pbTemp = pbBitmapData + (y-1)*ulBytesPerLine; /* Get this out of */
- /* the inner loop */
- for (x=0; x<ulSizeX; x++) { /* Now we have to calculate: */
- /***************************************************************/
- /* IM stores the image data sorted by color, i.e. RRRGGGBBB. */
- /* OS/2 on the other hand stores it pixelwise, i.e. RGBRGBRGB. */
- /* So we have to shuffle it: */
- /***************************************************************/
- *(pbTemp+x+x+x+2) = *(imbRowBuff+x );
- *(pbTemp+x+x+x+1) = *(imbRowBuff+x+ulSizeX );
- *(pbTemp+x+x+x ) = *(imbRowBuff+x+ulSizeX+ulSizeX);
- } /* Ende for x */
- ulProgress = 100 - (100 * y / ulSizeY); /* Calculate progress */
- WinPostMsg (hwndDlg, WM_PROGRESS, MPFROMSHORT(ulProgress), 0L);
- } /* Ende for y */
- fPicReadOK = TRUE;
- break;
-
- case IMGRY: /* The image data is the same with IMMAP */
- case IMMAP: /* and IMGRY. */
- if (usColors < 257) { /* IMMAP can have more than 256 colors in */
- /* the colormap, OS/2 not. */
- for (y=ulSizeY; y>0; y--) {
- if (DosWaitEventSem (semHalt, 0L) == ERROR_TIMEOUT) /* Test */
- goto Halt;
- imrrow (imBild, pbBitmapData+(y-1)*ulBytesPerLine); /* Get row */
- ulProgress = 100 - (100 * y / ulSizeY); /* Set progress */
- WinPostMsg (hwndDlg, WM_PROGRESS, MPFROMSHORT(ulProgress), 0L);
- } /* Ende for y */
- fPicReadOK = TRUE; /* Finished.. */
- } else { /* With more than 256 colors we have to */
- /* use a 24 bit picture in OS/2. */
- for (y=ulSizeY; y>0; y--) { /* Work row by row */
- if (DosWaitEventSem (semHalt, 0L) == ERROR_TIMEOUT) /* Test */
- goto Halt;
- if ((!imrrow (imBild, imbRowBuff)) && imerrnum) { /* Get row */
- ImErrorMsg (imerrnum);
- goto Halt;
- }
- /***************************************************************/
- /* Now we use IM's 'ideal pixel' function to calculate the 24 */
- /* bit value of each pixel and store it into the bitmap buffer */
- /***************************************************************/
- for (x=0; x<ulSizeX; x++) { /* Work pixel for pixel */
- impPixel = imrpix (imBild, imbRowBuff, (USHORT)x);
- pbTemp = pbBitmapData + (y-1)*ulBytesPerLine + x+x+x;
- *(pbTemp+2) = (BYTE)((impPixel & 0x0000FF));
- *(pbTemp+1) = (BYTE)((impPixel & 0x00FF00) >> 8);
- *(pbTemp ) = (BYTE)((impPixel & 0xFF0000) >> 16);
- }
- ulProgress = (USHORT) ((100L * (LONG)y) / (LONG)ulSizeY);
- WinPostMsg (hwndDlg, WM_PROGRESS, MPFROMSHORT(ulProgress), 0L);
- } /* Ende for y */
- fPicReadOK = TRUE; /* That's it */
- } /* Ende if */
- break;
- case GIF: /* GIF File */
- ulChunk = ulSizeY / 20; /* Read in in 20 "bites" */
- for (y=1; y<21; y++) { /* Check */
- if (DosWaitEventSem (semHalt, 0L) == ERROR_TIMEOUT)
- goto Halt;
- pbTemp = pbBitmapData + (ulSizeY - y * ulChunk) * ulBytesPerLine;
- gifrrows (hImage, pbTemp, ulSizeX, ulChunk); /* Get the rows */
- ulProgress = (USHORT) y*5; /* Set progress */
- WinPostMsg (hwndDlg, WM_PROGRESS, MPFROMSHORT(ulProgress), 0L);
- } /* endfor */
- ulChunk = ulSizeY % 20; /* Do we have some last rows? */
- if (ulChunk > 0) /* If so, read them in */
- gifrrows (hImage, pbBitmapData, ulSizeX, ulChunk);
- fPicReadOK = TRUE; /* That's it */
- break;
-
- } /* End switch */
-
- Halt: /* To this place we jump after the */
- /* read in was cancelled. */
-
- DosPostEventSem (semHalt); /* Erase semaphore */
-
- if (fPicReadOK == FALSE) /* Picture was not read in */
- free (pbBitmapData); /* free the buffer */
- if (imbRowBuff != NULL) /* If we have one, free this as */
- free (imbRowBuff); /* well */
-
- switch (usType) {
- case OS2_101:
- case WIN_3:
- case OS2_200:
- bmclose (hImage); /* Close the image files */
- break;
- case GIF:
- gifclose (hImage);
- break;
- default:
- imclose (imBild);
- }
-
- WinPostMsg (hwndDlg, WM_FINISHED, 0L, 0L); /* Inform the dialog box */
- /* that we are finished */
- } /* End of endless loop */
- }
- /************************* End of thread ReadFile ************************/
-
-
-
-
- /************************** Start of ShowMsg *****************************/
- /* */
- /* The function ShowMsg display a message. */
- /* */
- /***************************************************************************/
-
- VOID ShowMsg (LONG lTitle, LONG lMessage, ULONG ulIcon)
- {
- char cTitle[32];
- char cMessage[255];
-
- /* First the message title and the message content will be loaded */
- /* from the ressource part: */
- WinLoadString (hab, 0, lTitle, sizeof cTitle, cTitle);
- WinLoadString (hab, 0, lMessage, sizeof cMessage, cMessage);
-
- WinMessageBox (HWND_DESKTOP, /* Then the message will be displayed */
- hwndFrame,
- cMessage,
- cTitle,
- IDD_ERRORS,
- MB_OK | ulIcon);
- }
- /**************************** End of ShowMsg *****************************/
-
-
-
- /************************** Start of ImErrorMsg **************************/
- /* */
- /* ImErrorMsg shows an error message of the IM library. */
- /* */
- /***************************************************************************/
-
- VOID ImErrorMsg (int iMessageNum)
- {
- char cTitle[32];
-
- /* First we get the title of the message box: */
- WinLoadString (hab, 0, IDS_IMTITLE, sizeof cTitle, cTitle);
-
- WinMessageBox (HWND_DESKTOP, /* Then we show the message */
- hwndFrame,
- imerrors[iMessageNum],
- cTitle,
- IDD_ERRORS,
- MB_OK | MB_ERROR);
- }
-
- /*************************** End of ImErrorMsg ***************************/
-
-
-
- /************************ Start of GetFileType ***************************/
- /* */
- /* GetFileType gives the type of the stated file. */
- /* */
- /***************************************************************************/
- USHORT GetFileType (CHAR *szFileName, HFILE *hImage, IMAGE **imBild)
- {
- *hImage = bmopen (szFileName, "rb"); /* Try to open bitmap */
- if (*hImage != 0) /* ok? */
- return (BITMAP);
-
- *hImage = gifopen (szFileName, "rb"); /* Try to open GIF */
- if (*hImage != 0) /* ok? */
- return (GIF);
-
- *imBild = imopen (szFileName, "r"); /* Try to open IM */
- if (*imBild == NULL) /* ok? */
- if (imerrnum == 5) /* error 5 is "not im" */
- return (UNKNOWN); /* So give back "unknown" */
- else /* File is IM, but there's another */
- return (IMERROR); /* problem */
- else return (IM);
- }
- /*************************** End of GetFileType **************************/